from datetime import datetime
from typing import List, Optional
from pydantic import BaseModel
from bson import ObjectId

class PyObjectId(ObjectId):
    @classmethod
    def __get_validators__(cls):
        yield cls.validate

    @classmethod
    def validate(cls, v):
        if not ObjectId.is_valid(v):
            raise ValueError("Invalid objectid")
        return ObjectId(v)

    @classmethod
    def __modify_schema__(cls, field_schema):
        field_schema.update(type="string")

class MomentBase(BaseModel):
    content: str
    images: Optional[List[str]] = []
    is_public: bool = True

class MomentCreate(MomentBase):
    pass

class MomentUpdate(BaseModel):
    content: Optional[str] = None
    images: Optional[List[str]] = None
    is_public: Optional[bool] = None

class MomentInDBBase(MomentBase):
    id: PyObjectId
    user_id: PyObjectId
    like_count: int = 0
    comment_count: int = 0
    created_at: datetime
    updated_at: datetime

    class Config:
        arbitrary_types_allowed = True
        json_encoders = {ObjectId: str}

class Moment(MomentInDBBase):
    pass

class MomentInDB(MomentInDBBase):
    pass

class LikeBase(BaseModel):
    user_id: PyObjectId
    moment_id: PyObjectId

class LikeCreate(LikeBase):
    pass

class LikeInDBBase(LikeBase):
    id: PyObjectId
    created_at: datetime

    class Config:
        arbitrary_types_allowed = True
        json_encoders = {ObjectId: str}

class Like(LikeInDBBase):
    pass

class LikeInDB(LikeInDBBase):
    pass

class CommentBase(BaseModel):
    content: str
    moment_id: PyObjectId
    parent_comment_id: Optional[PyObjectId] = None

class CommentCreate(CommentBase):
    pass

class CommentUpdate(BaseModel):
    content: Optional[str] = None

class CommentInDBBase(CommentBase):
    id: PyObjectId
    user_id: PyObjectId
    created_at: datetime

    class Config:
        arbitrary_types_allowed = True
        json_encoders = {ObjectId: str}

class Comment(CommentInDBBase):
    pass

class CommentInDB(CommentInDBBase):
    pass